package paim.gh.model.DAO;


import java.util.ArrayList;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;

import paim.wingchun.app.Reflections;
import paim.wingchun.model.DAO.DAO;
import paim.wingchun.model.pojos.Pojo;

import paim.gh.model.Gradeavel;
import paim.gh.model.GradeavelException;
import paim.gh.model.pojos.*;

import static paim.wingchun.app.Reflections.getFieldName;

// <T extends Parent> accepts either Parent or Child while <T super Parent> accepts either Parent or Grandparent.
// ? extends Type: Denotes a family of subtypes of type Type. This is the most useful wildcard.
// ? super Type: Denotes a family of supertypes of type Type.
// ?: Denotes the set of all types or any.

/** @author paim 13/09/2013
 * @since */
abstract class AbstractGradeavelDAO<P extends Pojo & Gradeavel> extends DAO<P> /* implements ContratoGradeavel<P> */{

    public List<P> list(Session session, Grade grade) {
       //Class<P> parameter_class = Reflections.getPojoParameter(this.getClass());
        Class<P> parameter_class = getpClass();
        
        StringBuffer consulta = new StringBuffer();
        consulta.append("SELECT  o FROM o IN CLASS").append(parameter_class.getSimpleName());
        consulta.append("       WHERE o");

        if ( Turma.class.isAssignableFrom(parameter_class) )
            consulta.append(".aula");
        else if ( Aula.class.isAssignableFrom(parameter_class) )
            ;
        else if ( Periodo.class.isAssignableFrom(parameter_class) )
            consulta.append(".turma.aula");
        else if ( Professor.class.isAssignableFrom(parameter_class) )
            ;
        else
            throw new GradeavelException();

        consulta.append((".grade.id = :id_grade"));

        Query query = session.createQuery(consulta.toString());
        query.setLong("id_grade", grade.getId());
        return query.list();
    }

    final <T extends Pojo> List<P> list_by(Session session, Grade grade, T pojo) {
        StringBuffer consulta;
        Class<? extends Pojo> classe = pojo.getClass();
        //Class<P> parameter_class = Reflections.getPojoParameter(this.getClass());
        Class<P> parameter_class = getpClass();
        
        if ( Turma.class.isAssignableFrom(parameter_class) )
            consulta = consulta_by_turma(classe, false);

        else if ( Aula.class.isAssignableFrom(parameter_class) )
            consulta = consulta_by_aula(classe, false);

        else if ( Periodo.class.isAssignableFrom(parameter_class) )
            consulta = consulta_by_periodo(classe, false);

        else if ( Professor.class.isAssignableFrom(parameter_class) )
            consulta = consulta_by_professor(classe, false);

        else
            throw new GradeavelException();

        Query query = session.createQuery(consulta.toString());
        query.setLong("id_grade", grade.getId());
        query.setLong("id_pojo", pojo.getId());

        return query.list();
    }

    final <T extends Pojo> List<P> list_by_s(Session session, Grade grade, List<T> pojos) {
        Class<T> classe = Reflections.getClasse(pojos);
        StringBuffer consulta;

        //Class<P> parameter_class = Reflections.getPojoParameter(this.getClass());
        Class<P> parameter_class = getpClass();
        
        if ( Turma.class.isAssignableFrom(parameter_class) )
            consulta = consulta_by_turma(classe, true);

        else if ( Aula.class.isAssignableFrom(parameter_class) )
            consulta = consulta_by_aula(classe, true);

        else if ( Periodo.class.isAssignableFrom(parameter_class) )
            consulta = consulta_by_periodo(classe, true);

        else if ( Professor.class.isAssignableFrom(parameter_class) )
            consulta = consulta_by_professor(classe, true);

        else
            throw new GradeavelException();

        Query query = session.createQuery(consulta.toString());
        query.setLong("id_grade", grade.getId());
        query.setParameterList("ids", Pojo.ids(pojos));

        return query.list();
    }

    private StringBuffer consulta_by_periodo(Class<? extends Pojo> classe, boolean isLista) {
        StringBuffer consulta = new StringBuffer();
        consulta.append("SELECT  DISTINCT periodo FROM periodo IN CLASS " + Periodo.class.getSimpleName());
        String inner_curso = "       INNER JOIN FETCH periodo.turma.aula.disciplina.cursos curso";
        String where = "       WHERE periodo.turma.aula.grade.id = :id_grade";
        String and = "    AND ";
        String right_side = (isLista ? ".id IN (:ids) " : ".id = :id_pojo");

        if ( Turma.class.isAssignableFrom(classe) ) {
            consulta.append(where).append(and);
            consulta.append("periodo.turma");
        }
        else if ( Sala.class.isAssignableFrom(classe) ) {
            consulta.append(where).append(and);
            consulta.append("periodo.sala");
        }
        else if ( Dia.class.isAssignableFrom(classe) ) {
            consulta.append(where).append(and);
            consulta.append("periodo.dia");
        }
        else if ( Horario.class.isAssignableFrom(classe) ) {
            consulta.append(where).append(and);
            consulta.append("periodo.horario");
        }
        else if ( Turno.class.isAssignableFrom(classe) ) {
            consulta.append(where).append(and);
            consulta.append("periodo.horario.turno");
        }
        else if ( Professor.class.isAssignableFrom(classe) ) {
            consulta.append(where).append(and);
            consulta.append("periodo.professor");
        }
        else if ( Doscente.class.isAssignableFrom(classe) ) {
            consulta.append(where).append(and);
            consulta.append("periodo.professor.doscente");
        }
        else if ( Aula.class.isAssignableFrom(classe) ) {
            consulta.append(where).append(and);
            consulta.append("periodo.turma.aula");
        }
        else if ( Disciplina.class.isAssignableFrom(classe) ) {
            consulta.append(where).append(and);
            consulta.append("periodo.turma.aula.disciplina ");
        }
        else if ( Semestre.class.isAssignableFrom(classe) ) {
            consulta.append(where).append(and);
            consulta.append("periodo.turma.aula.disciplina.semestre");
        }
        else if ( Curso.class.isAssignableFrom(classe) ) {
            consulta.append(inner_curso);
            consulta.append(where).append(and);
            consulta.append("curso");
        }
        else
            throw new GradeavelException();
        consulta.append(right_side);

        return consulta;
    }

    private StringBuffer consulta_by_turma(Class<? extends Pojo> classe, boolean isLista) {
        StringBuffer consulta = new StringBuffer();
        consulta.append("SELECT  DISTINCT turma FROM turma IN CLASS " + Turma.class.getSimpleName());
        String inner_periodo = "       INNER JOIN FETCH turma.periodos periodo";
        String inner_curso = "       INNER JOIN FETCH turma.aula.disciplina.cursos curso";

        String where = "       WHERE turma.aula.grade.id = :id_grade";

        String and = "    AND ";
        String right_side = (isLista ? ".id IN (:ids) " : ".id = :id_pojo");

        if ( Periodo.class.isAssignableFrom(classe) ) {
            consulta.append(inner_periodo);
            consulta.append(where).append(and);
            consulta.append("periodo ");
        }
        else if ( Professor.class.isAssignableFrom(classe) ) {
            consulta.append(inner_periodo);
            consulta.append(where).append(and);
            consulta.append("periodo.professor ");
        }
        else if ( Doscente.class.isAssignableFrom(classe) ) {
            consulta.append(inner_periodo);
            consulta.append(where).append(and);
            consulta.append("periodo.professor.doscente ");
        }
        else if ( Dia.class.isAssignableFrom(classe) ) {
            consulta.append(inner_periodo);
            consulta.append(where).append(and);
            consulta.append("periodo.dia ");
        }
        else if ( Sala.class.isAssignableFrom(classe) ) {
            consulta.append(inner_periodo);
            consulta.append(where).append(and);
            consulta.append("periodo.sala ");
        }
        else if ( Horario.class.isAssignableFrom(classe) ) {
            consulta.append(inner_periodo);
            consulta.append(where).append(and);
            consulta.append("periodo.horario ");
        }
        else if ( Turno.class.isAssignableFrom(classe) ) {
            consulta.append(inner_periodo);
            consulta.append(where).append(and);
            consulta.append("periodo.horario.turno ");
        }
        else if ( Aula.class.isAssignableFrom(classe) ) {
            consulta.append(where).append(and);
            consulta.append("turma.aula ");
        }
        else if ( Disciplina.class.isAssignableFrom(classe) ) {
            consulta.append(where).append(and);
            consulta.append("turma.aula.disciplina ");
        }
        else if ( Semestre.class.isAssignableFrom(classe) ) {
            consulta.append(where).append(and);
            consulta.append("turma.aula.disciplina.semestre ");
        }
        else if ( Curso.class.isAssignableFrom(classe) ) {
            consulta.append(inner_curso);
            consulta.append(where).append(and);
            consulta.append("curso ");
        }
        else
            throw new GradeavelException();

        consulta.append(right_side);

        return consulta;
    }

    private StringBuffer consulta_by_aula(Class<? extends Pojo> classe, boolean isLista) {
        StringBuffer consulta = new StringBuffer();
        consulta.append("SELECT  DISTINCT aula FROM aula IN CLASS " + Aula.class.getSimpleName());
        String inner_turma = "       INNER JOIN FETCH aula.turmas turma";
        String inner_periodo = "       INNER JOIN FETCH turma.periodos periodo";
        String inner_curso = "       INNER JOIN FETCH aula.disciplina.cursos curso";
        String where = "       WHERE aula.grade.id = :id_grade";

        String and = "    AND ";
        String right_side = (isLista ? ".id IN (:ids) " : ".id = :id_pojo");

        if ( Periodo.class.isAssignableFrom(classe) ) {
            consulta.append(inner_turma);
            consulta.append(inner_periodo);
            consulta.append(where).append(and);
            consulta.append("periodo");
        }
        else if ( Professor.class.isAssignableFrom(classe) ) {
            consulta.append(inner_turma);
            consulta.append(inner_periodo);
            consulta.append(where).append(and);
            consulta.append("periodo.professor");
        }
        else if ( Doscente.class.isAssignableFrom(classe) ) {
            consulta.append(inner_turma);
            consulta.append(inner_periodo);
            consulta.append(where).append(and);
            consulta.append("periodo.professor.doscente");
        }
        else if ( Dia.class.isAssignableFrom(classe) ) {
            consulta.append(inner_turma);
            consulta.append(inner_periodo);
            consulta.append(where).append(and);
            consulta.append("periodo.dia");
        }
        else if ( Sala.class.isAssignableFrom(classe) ) {
            consulta.append(inner_turma);
            consulta.append(inner_periodo);
            consulta.append(where).append(and);
            consulta.append("periodo.sala");
        }
        else if ( Horario.class.isAssignableFrom(classe) ) {
            consulta.append(inner_turma);
            consulta.append(inner_periodo);
            consulta.append(where).append(and);
            consulta.append("periodo.horario");
        }
        else if ( Turno.class.isAssignableFrom(classe) ) {
            consulta.append(inner_turma);
            consulta.append(inner_periodo);
            consulta.append(where).append(and);
            consulta.append("periodo.horario.turno");
        }
        else if ( Disciplina.class.isAssignableFrom(classe) ) {
            consulta.append(where).append(and);
            consulta.append("aula.disciplina");
        }
        else if ( Semestre.class.isAssignableFrom(classe) ) {
            consulta.append(where).append(and);
            consulta.append("aula.disciplina.semestre");
        }
        else if ( Turma.class.isAssignableFrom(classe) ) {
            consulta.append(inner_turma);
            consulta.append(where).append(and);
            consulta.append("turma");
        }
        else if ( Curso.class.isAssignableFrom(classe) ) {
            consulta.append(inner_curso);
            consulta.append(where).append(and);
            consulta.append("curso");
        }
        else
            throw new GradeavelException();

        consulta.append(right_side);
        return consulta;
    }

    private StringBuffer consulta_by_professor(Class<? extends Pojo> classe, boolean isLista) {
        StringBuffer consulta = new StringBuffer();
        consulta.append("SELECT  DISTINCT professor FROM professor IN CLASS " + Professor.class.getSimpleName());
        String inner_periodo = "       INNER JOIN FETCH professor.periodos periodo";
        String inner_curso = "       INNER JOIN FETCH  periodo.turma.aula.disciplina.cursos curso";
        String where = "       WHERE professor.grade.id = :id_grade";

        String and = "    AND ";
        String right_side = (isLista ? ".id IN (:ids) " : ".id = :id_pojo");

        if ( Periodo.class.isAssignableFrom(classe) ) {
            consulta.append(inner_periodo);
            consulta.append(where).append(and);
            consulta.append("periodo");
        }
        else if ( Dia.class.isAssignableFrom(classe) ) {
            consulta.append(inner_periodo);
            consulta.append(where).append(and);
            consulta.append("periodo.dia");
        }
        else if ( Sala.class.isAssignableFrom(classe) ) {
            consulta.append(inner_periodo);
            consulta.append(where).append(and);
            consulta.append("periodo.sala");
        }
        else if ( Turma.class.isAssignableFrom(classe) ) {
            consulta.append(inner_periodo);
            consulta.append(where).append(and);
            consulta.append("periodo.turma");
        }
        else if ( Aula.class.isAssignableFrom(classe) ) {
            consulta.append(inner_periodo);
            consulta.append(where).append(and);
            consulta.append("periodo.turma.aula");
        }
        else if ( Disciplina.class.isAssignableFrom(classe) ) {
            consulta.append(inner_periodo);
            consulta.append(where).append(and);
            consulta.append("periodo.turma.aula.disciplina");
        }
        else if ( Semestre.class.isAssignableFrom(classe) ) {
            consulta.append(inner_periodo);
            consulta.append(where).append(and);
            consulta.append("periodo.turma.aula.disciplina.semestre");
        }
        else if ( Doscente.class.isAssignableFrom(classe) ) {
            consulta.append(inner_periodo);
            consulta.append(where).append(and);
            consulta.append("periodo.professor.doscente");
        }
        else if ( Horario.class.isAssignableFrom(classe) ) {
            consulta.append(inner_periodo);
            consulta.append(where).append(and);
            consulta.append("periodo.horario");
        }
        else if ( Turno.class.isAssignableFrom(classe) ) {
            consulta.append(inner_periodo);
            consulta.append(where).append(and);
            consulta.append("periodo.horario.turno");
        }
        else if ( Curso.class.isAssignableFrom(classe) ) {
            consulta.append(inner_periodo);
            consulta.append(inner_curso);
            consulta.append(where).append(and);
            consulta.append("curso");
        }
        else
            throw new GradeavelException();

        consulta.append(right_side);
        return consulta;
    }

    final <T extends Pojo> List<T> get_from_periodo_by(Session session, P pojo, Class<T> classe) {
        StringBuffer consulta = consulta_from_periodo(classe, (Class<P>) pojo.getClass(), false);

        Query query = session.createQuery(consulta.toString());
        query.setLong("id_pojo", pojo.getId());

        return query.list();
    }

    final <T extends Pojo> List<T> get_from_periodo_by_s(Session session, List<P> pojos, Class<T> classe) {
        StringBuffer consulta = consulta_from_periodo(classe, Reflections.getClasse(pojos), false);

        Query query = session.createQuery(consulta.toString());
        query.setParameterList("ids", Pojo.ids(pojos));

        return query.list();
    }

    private StringBuffer consulta_from_periodo(Class<? extends Pojo> classe, Class<P> where_class, boolean isLista) {
        StringBuffer consulta = new StringBuffer();
        consulta.append("SELECT  DISTINCT ");

        if ( Periodo.class.isAssignableFrom(classe) ) {
            consulta.append(getFieldName(classe));
        }
        else if ( Sala.class.isAssignableFrom(classe) ) {
            consulta.append("periodo.").append(getFieldName(classe));
        }
        else if ( Dia.class.isAssignableFrom(classe) ) {
            consulta.append("periodo.").append(getFieldName(classe));
        }
        else if ( Professor.class.isAssignableFrom(classe) ) {
            consulta.append("periodo.").append(getFieldName(classe));
        }
        else if ( Horario.class.isAssignableFrom(classe) ) {
            consulta.append("periodo.").append(getFieldName(classe));
        }
        else if ( Turma.class.isAssignableFrom(classe) ) {
            consulta.append("periodo.").append(getFieldName(classe));
        }
        else if ( Turno.class.isAssignableFrom(classe) ) {
            consulta.append("periodo.horario.").append(getFieldName(classe));
        }
        else if ( Doscente.class.isAssignableFrom(classe) ) {
            consulta.append("periodo.professor.").append(getFieldName(classe));
        }
        else if ( Aula.class.isAssignableFrom(classe) ) {
            consulta.append("periodo.turma.").append(getFieldName(classe));
        }
        else if ( Disciplina.class.isAssignableFrom(classe) ) {
            consulta.append("periodo.turma.aula.").append(getFieldName(classe));
        }
        else if ( Semestre.class.isAssignableFrom(classe) ) {
            consulta.append("periodo.turma.aula.disciplina.").append(getFieldName(classe));
        }
        else if ( Curso.class.isAssignableFrom(classe) ) {
            consulta.append(getFieldName(classe));
        }
        else
            throw new GradeavelException();

        consulta.append(" FROM periodo IN CLASS " + Periodo.class.getSimpleName());

        if ( Curso.class.isAssignableFrom(classe) ) {
            consulta.append("       INNER JOIN FETCH periodo.turma.aula.disciplina.cursos curso");
        }

        consulta.append("       WHERE ");
        consulta.append("        periodo.");

        if ( Periodo.class.isAssignableFrom(where_class) ) {
            consulta.append("turma.").append(getFieldName(where_class));
        }
        else if ( Turma.class.isAssignableFrom(where_class) ) {
            consulta.append(getFieldName(where_class));
        }
        else if ( Professor.class.isAssignableFrom(where_class) ) {
            consulta.append(getFieldName(where_class));
        }
        else if ( Aula.class.isAssignableFrom(where_class) ) {
            consulta.append("turma.").append(getFieldName(where_class));
        }

        consulta.append((isLista ? ".id IN (:ids) " : ".id = :id_pojo"));

        return consulta;
    }

    public static void main(String[] args) {

        List<Class<? extends Pojo>> classes = new ArrayList<>();
        classes.add(Sala.class);
        classes.add(Dia.class);
        classes.add(Professor.class);
        classes.add(Horario.class);
        classes.add(Turno.class);
        classes.add(Doscente.class);
        classes.add(Aula.class);
        classes.add(Disciplina.class);
        classes.add(Semestre.class);
        classes.add(Curso.class);

        for ( @SuppressWarnings("unused")
        Class<? extends Pojo> class1 : classes ) {
            // System.out.println(consulta_from_periodo(class1, false));
            // System.out.println(consulta_from_periodo(class1, true));
        }
    }

    // ///////////////////////////////////////////////////////////////////////////////////

    public List<P> list_by_Professor(Session session, Grade grade, Professor pojo) {
        return list_by(session, grade, pojo);
    }

    public List<P> list_by_Professores(Session session, Grade grade, List<Professor> pojos) {
        return list_by_s(session, grade, pojos);
    }

    public List<P> list_by_Periodo(Session session, Grade grade, Periodo pojo) {
        return list_by(session, grade, pojo);
    }

    public List<P> list_by_Periodos(Session session, Grade grade, List<Periodo> pojos) {
        return list_by_s(session, grade, pojos);
    }

    public List<P> list_by_Aula(Session session, Grade grade, Aula pojo) {
        return list_by(session, grade, pojo);
    }

    public List<P> list_by_Aulas(Session session, Grade grade, List<Aula> pojos) {
        return list_by_s(session, grade, pojos);
    }

    public List<P> list_by_Turma(Session session, Grade grade, Turma pojo) {
        return list_by(session, grade, pojo);
    }

    public List<P> list_by_Turmas(Session session, Grade grade, List<Turma> pojos) {
        return list_by_s(session, grade, pojos);
    }

    public List<P> list_by_Disciplina(Session session, Grade grade, Disciplina pojo) {
        return list_by(session, grade, pojo);
    }

    public List<P> list_by_Disciplinas(Session session, Grade grade, List<Disciplina> pojos) {
        return list_by_s(session, grade, pojos);
    }

    public List<P> list_by_Doscente(Session session, Grade grade, Doscente pojo) {
        return list_by(session, grade, pojo);
    }

    public List<P> list_by_Doscentes(Session session, Grade grade, List<Doscente> pojos) {
        return list_by_s(session, grade, pojos);
    }

    public final List<P> list_by_Curso(Session session, Grade grade, Curso pojo) {
        return list_by(session, grade, pojo);
    }

    public final List<P> list_by_Cursos(Session session, Grade grade, List<Curso> pojos) {
        return list_by_s(session, grade, pojos);
    }

    public final List<P> list_by_Dia(Session session, Grade grade, Dia pojo) {
        return list_by(session, grade, pojo);
    }

    public final List<P> list_by_Dias(Session session, Grade grade, List<Dia> pojos) {
        return list_by_s(session, grade, pojos);
    }

    public final List<P> list_by_Horario(Session session, Grade grade, Horario pojo) {
        return list_by(session, grade, pojo);
    }

    public final List<P> list_by_Horarios(Session session, Grade grade, List<Horario> pojos) {
        return list_by_s(session, grade, pojos);
    }

    public final List<P> list_by_Sala(Session session, Grade grade, Sala pojo) {
        return list_by(session, grade, pojo);
    }

    public final List<P> list_by_Salas(Session session, Grade grade, List<Sala> pojos) {
        return list_by_s(session, grade, pojos);
    }

    public final List<P> list_by_Semestre(Session session, Grade grade, Semestre pojo) {
        return list_by(session, grade, pojo);
    }

    public final List<P> list_by_Semestres(Session session, Grade grade, List<Semestre> pojos) {
        return list_by_s(session, grade, pojos);
    }

    public final List<P> list_by_Turno(Session session, Grade grade, Turno pojo) {
        return list_by(session, grade, pojo);
    }

    public final List<P> list_by_Turnos(Session session, Grade grade, List<Turno> pojos) {
        return list_by_s(session, grade, pojos);
    }

    public List<Periodo> getPeriodos(Session session, P pojo) {
        return get_from_periodo_by(session, pojo, Periodo.class);
    }

    public List<Periodo> getPeriodos(Session session, List<P> pojos) {
        return get_from_periodo_by_s(session, pojos, Periodo.class);
    }

    public List<Aula> getAulas(Session session, P pojo) {
        return get_from_periodo_by(session, pojo, Aula.class);
    }

    public List<Aula> getAulas(Session session, List<P> pojos) {
        return get_from_periodo_by_s(session, pojos, Aula.class);
    }

    public List<Professor> getProfessores(Session session, P pojo) {
        return get_from_periodo_by(session, pojo, Professor.class);
    }

    public List<Professor> getProfessores(Session session, List<P> pojos) {
        return get_from_periodo_by_s(session, pojos, Professor.class);
    }

    public List<Turma> getTurmas(Session session, P pojo) {
        return get_from_periodo_by(session, pojo, Turma.class);
    }

    public List<Turma> getTurmas(Session session, List<P> pojos) {
        return get_from_periodo_by_s(session, pojos, Turma.class);
    }

    public List<Disciplina> getDisciplinas(Session session, P pojo) {
        return get_from_periodo_by(session, pojo, Disciplina.class);
    }

    public List<Disciplina> getDisciplinas(Session session, List<P> pojos) {
        return get_from_periodo_by_s(session, pojos, Disciplina.class);
    }

    public List<Doscente> getDoscentes(Session session, P pojo) {
        return get_from_periodo_by(session, pojo, Doscente.class);
    }

    public List<Doscente> getDoscentes(Session session, List<P> pojos) {
        return get_from_periodo_by_s(session, pojos, Doscente.class);
    }

    public final List<Curso> getCursos(Session session, P pojo) {
        return get_from_periodo_by(session, pojo, Curso.class);
    }

    public final List<Curso> getCursos(Session session, List<P> pojos) {
        return get_from_periodo_by_s(session, pojos, Curso.class);
    }

    public final List<Dia> getDias(Session session, P pojo) {
        return get_from_periodo_by(session, pojo, Dia.class);
    }

    public final List<Dia> getDias(Session session, List<P> pojos) {
        return get_from_periodo_by_s(session, pojos, Dia.class);
    }

    public final List<Horario> getHorarios(Session session, P pojo) {
        return get_from_periodo_by(session, pojo, Horario.class);
    }

    public final List<Horario> getHorarios(Session session, List<P> pojos) {
        return get_from_periodo_by_s(session, pojos, Horario.class);
    }

    public final List<Sala> getSalas(Session session, P pojo) {
        return get_from_periodo_by(session, pojo, Sala.class);
    }

    public final List<Sala> getSalas(Session session, List<P> pojos) {
        return get_from_periodo_by_s(session, pojos, Sala.class);
    }

    public final List<Semestre> getSemestres(Session session, P pojo) {
        return get_from_periodo_by(session, pojo, Semestre.class);
    }

    public final List<Semestre> getSemestres(Session session, List<P> pojos) {
        return get_from_periodo_by_s(session, pojos, Semestre.class);
    }

    public final List<Turno> getTurnos(Session session, P pojo) {
        return get_from_periodo_by(session, pojo, Turno.class);
    }

    public final List<Turno> getTurnos(Session session, List<P> pojos) {
        return get_from_periodo_by_s(session, pojos, Turno.class);
    }

    @Deprecated
    private <T extends Pojo> List<T> antigo_get_byTurma(Session session, Turma turma, Class<T> classe) {

        StringBuffer consulta = new StringBuffer();
        consulta.append("SELECT DISTINCT pojo FROM pojo IN CLASS " + classe.getSimpleName());
        consulta.append(" WHERE pojo.id IN ");
        consulta.append(" (");
        consulta.append("        SELECT periodo." + getFieldName(classe));
        consulta.append("        FROM " + Periodo.class.getSimpleName() + " periodo ");
        consulta.append("        WHERE periodo.turma.id = :idTurma ");
        consulta.append(" )");

        Query query = session.createQuery(consulta.toString());
        query.setLong("idTurma", turma.getId());

        return query.list();
    }
    // ###########################################################
    //
    // public List<Aula> getAulas(Session session, Periodo pojo) {
    // StringBuffer consulta = new StringBuffer();
    // consulta.append("SELECT  DISTINCT o FROM o IN CLASS " + Aula.class.getSimpleName());
    // consulta.append("       INNER JOIN FETCH o.turmas turma");
    // consulta.append("       INNER JOIN FETCH turma.periodos periodo");
    // consulta.append("             WHERE periodo.id = :id_pojo");
    // Query query = session.createQuery(consulta.toString());
    // query.setLong("id_pojo", pojo.getId());
    //
    // return query.list();
    // }
    //
    // public List<Turma> getTurmas(Session session, Periodo pojo) {
    // StringBuffer consulta = new StringBuffer();
    // consulta.append("SELECT  DISTINCT o FROM o IN CLASS " + Turma.class.getSimpleName());
    // consulta.append("       INNER JOIN FETCH o.periodos periodo");
    // consulta.append("             WHERE periodo.id = :id_pojo");
    // Query query = session.createQuery(consulta.toString());
    // query.setLong("id_pojo", pojo.getId());
    //
    // return query.list();
    // }
    //
    // public List<Professor> getProfessores(Session session, Periodo pojo) {
    // StringBuffer consulta = new StringBuffer();
    // consulta.append("SELECT  DISTINCT o FROM o IN CLASS " + Professor.class.getSimpleName());
    // consulta.append("       INNER JOIN FETCH o.periodos periodo");
    // consulta.append("             WHERE periodo.id = :id_pojo");
    // Query query = session.createQuery(consulta.toString());
    // query.setLong("id_pojo", pojo.getId());
    //
    // return query.list();
    // }
    //
    // public List<Professor> getProfessores(Session session, Aula pojo) {
    // StringBuffer consulta = new StringBuffer();
    // consulta.append("SELECT  DISTINCT o FROM o IN CLASS " + Professor.class.getSimpleName());
    // consulta.append("       INNER JOIN FETCH o.periodos periodo");
    // consulta.append("             WHERE periodo.turma.aula.id = :id_pojo");
    //
    // Query query = session.createQuery(consulta.toString());
    // query.setLong("id_pojo", pojo.getId());
    //
    // return query.list();
    // }
    //
    // public List<Turma> getTurmas(Session session, Aula pojo) {
    // StringBuffer consulta = new StringBuffer();
    // consulta.append("SELECT  DISTINCT o FROM o IN CLASS " + Turma.class.getSimpleName());
    // consulta.append("             WHERE periodo.professor.id = :id_pojo");
    // Query query = session.createQuery(consulta.toString());
    // query.setLong("id_pojo", pojo.getId());
    //
    // return query.list();
    // }

    // @Deprecated
    // public List<Professor> getProfessores(Session session, Turma turma) {
    // return PeriodoDAO.getInstance().antigo_get_byTurma(session, turma, Professor.class);
    // }

}
